package end.controller;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import redis.clients.jedis.Jedis;
import end.bean.Album;
import end.bean.Chapter;
import end.ser.ChapterSER;
import end.util.jedis.JedisPoolUtils;

/**
 * 
 * ChapterForController.java 2016-6-29
 * 
 * Copyright zhaocj Inc. All rights reserved. Love Me Like Love Justin Bieber
 */
@Controller
@RequestMapping("/chapter/")
public class ChapterForController {
	private final static Logger logger = LogManager
			.getLogger(AlbumForController.class);

	@Autowired
	private ChapterSER<Chapter> chapterSER;

	public ChapterSER<Chapter> getChapterSER() {
		return chapterSER;
	}

	public void setChapterSER(ChapterSER<Chapter> chapterSER) {
		this.chapterSER = chapterSER;
	}

	@RequestMapping("queryChaptersByPage")
	public @ResponseBody
	Map<String, Object> queryChaptersByPage(Integer album_id, Integer page,
			Integer rows, String sort, String order) throws Exception {
		Chapter chapter = new Chapter();
		chapter.getPageUtil().setPaging(true);
		chapter.getPageUtil().setOrderByCondition(sort);
		chapter.getPageUtil().setQueryCondition(order);
		chapter.getPageUtil().setPageOffset((page - 1) * rows);
		chapter.getPageUtil().setPageSize(rows);
		chapter.getAlbum().setId(album_id);
		List<Chapter> beans = chapterSER.selectByBean(chapter);
		Map<String, Object> rets = new HashMap<String, Object>();
		rets.put("total", chapterSER.selectByBeanCount(chapter));
		rets.put("rows", beans);
		return rets;
	}

	@RequestMapping("queryChart")
	public @ResponseBody
	Map<String, Object> queryChart(Album album) throws Exception {
		Map<String, Object> rets = new HashMap<String, Object>();
		Jedis jedis = JedisPoolUtils.getJedis();
		jedis.select(6);
		List<Integer> chartY = new ArrayList<Integer>();
		List<String> chartX = new ArrayList<String>();
		Set<String> zrange = jedis.zrangeByScore("album" + album.getId(), 0,
				10000, 0, 5);
		for (String chapterStr : zrange) {
			String subChapterStr = chapterStr.substring(
					chapterStr.indexOf("+_+") + 3, chapterStr.length());
			chartX.add(subChapterStr.substring(0, subChapterStr.indexOf(".")));
			chartY.add(Integer.parseInt(jedis.get(chapterStr)));
		}
		rets.put("chartX", chartX);
		rets.put("chartY", chartY);
		JedisPoolUtils.close(jedis);
		return rets;
	}

	@RequestMapping("download/{albumID}/{chapterID}/{*}/{*}")
	public void downloadFile(HttpServletResponse response,
			HttpServletRequest request,
			@PathVariable("albumID") Integer albumID,
			@PathVariable("chapterID") Integer chapterID) throws Exception {

		/**
		 * spring 会对?号后面的参数进行utf-8的编码，但是不会对前面的编码，前面的编码还是ISO-8859-1
		 */
		String requestURL = URLDecoder.decode(request.getRequestURI(), "UTF-8");
		String urlName = requestURL.substring(requestURL.lastIndexOf("/",
				requestURL.lastIndexOf("/") - 1) + 1);

		File file = new File(ChapterForController.class.getResource("/")
				.getPath());
		String rootPath = file.getParentFile().getParentFile().toURI()
				.getPath();
		String downloadUrl = rootPath + "static/file/album/" + urlName;
		String fileName = requestURL.substring(requestURL.lastIndexOf("/") + 1);
		String albumName = urlName.split("/")[0];
		// 为下载的文件的次数排序服务+
		Jedis jedis = JedisPoolUtils.getJedis();
		jedis.select(6);
		jedis.incr("chapter:" + chapterID + "+_+" + fileName);
		jedis.zadd(
				"album" + albumID,
				Double.valueOf(jedis.get("chapter:" + chapterID + "+_+"
						+ fileName)), "chapter:" + chapterID + "+_+" + fileName);
		// 为下载的文件的次数排序服务-
		// 为专辑下载次数排序服务+
		jedis.incr("album:" + albumID + "+_+" + albumName);
		jedis.zadd("album", Double.valueOf(jedis.get("album:" + albumID + "+_+"
				+ albumName)), "album:" + albumID + "+_+" + albumName);
		// 为专辑下载次数排序服务-
		File proposeFile = new File(downloadUrl);
		long fSize = proposeFile.length();
		response.setContentType("application/x-download");
		response.setHeader("Accept-Ranges", "bytes");
		response.setHeader("Content-Length", String.valueOf(fSize));
		response.setHeader("Content-Disposition", "attachment; filename="
				+ new String(fileName.getBytes("UTF-8"), "ISO-8859-1"));
		long pos = 0;
		if (null != request.getHeader("Range")) {
			// 断点续传
			response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);

			try {
				pos = Long.parseLong(request.getHeader("Range")
						.replaceAll("bytes=", "").replaceAll("-", ""));
			} catch (NumberFormatException e) {
				logger.error("range  ----不是一个整数-- ");
				pos = 0;
			}
		}

		ServletOutputStream out = response.getOutputStream();
		BufferedOutputStream bufferOut = new BufferedOutputStream(out);
		InputStream inputStream = new FileInputStream(proposeFile);
		String contentRange = new StringBuffer("bytes ")
				.append(new Long(pos).toString()).append("-")
				.append(new Long(fSize - 1).toString()).append("/")
				.append(new Long(fSize).toString()).toString();
		response.setHeader("Content-Range", contentRange);
		inputStream.skip(pos);
		byte[] buffer = new byte[5 * 1024];
		int length = 0;
		while ((length = inputStream.read(buffer, 0, buffer.length)) != -1) {
			bufferOut.write(buffer, 0, length);
		}
		bufferOut.flush();
		bufferOut.close();
		out.close();
		inputStream.close();
		JedisPoolUtils.close(jedis);
	}

	@RequestMapping("drop")
	public @ResponseBody
	boolean dropChapterBy(Integer id) throws Exception {
		chapterSER.deleteByPrimaryKey(id);
		if (logger.isDebugEnabled()) {
			logger.debug("数据  {} 被删除 ：" + id);
		}
		return true;
	}

}
